package com.norman.sorry.core.cards;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;

import com.norman.sorry.core.moves.IMove;
import com.norman.sorry.core.moves.MoveFactory;
import com.norman.sorry.core.pieces.IPiece;
import com.norman.sorry.core.players.IPlayer;
import com.norman.sorry.core.tiles.ILinkedTile;
import com.norman.sorry.core.tiles.TileUtils;

/**
 * The class representation of the seven card. This card allows the player to
 * move any game piece seven tiles forward or split the move of seven tiles
 * between any two game pieces the player controls that are on the board. This
 * card cannot be used to move a game piece out of start.
 * 
 * @author Brian Norman
 * @version 0.0.1 beta
 * @since 0.0.1 beta
 */
public class Seven extends AbstractCard {

   /**
    * Definition of the constant integer seven.
    */
   public static final int SEVEN = 7;

   /**
    * {@inheritDoc}
    * 
    * Returns the moves of each game piece moving seven tiles forward that can
    * and every possible split between to pieces that is legal.
    * 
    * @see com.norman.sorry.core.cards.ICard#getMoves(IPlayer, Map)
    */
   @Override
   public Collection<IMove> getMoves(IPlayer player, Map<IPiece, ILinkedTile> pieces) {
      Collection<IMove> moves = getMoves(player, pieces, SEVEN);
      for (int i = 1; SEVEN - i >= i; i++) {
         moves.addAll(getMoves(player, pieces, SEVEN - i, i));
      }
      return moves;
   }

   /**
    * Calculates the possible moves given the specified split.
    * 
    * @param player
    *           the player that drew the card.
    * @param pieces
    *           all the game pieces and what tile they are mapped to.
    * @param first
    *           how many tiles the first piece will move.
    * @param second
    *           how many tiles the second piece will move.
    * @return all the possible moves.
    */
   private Collection<IMove> getMoves(IPlayer player, Map<IPiece, ILinkedTile> pieces, int first, int second) {
      Collection<IMove> moves = new LinkedList<IMove>();

      for (IPiece piece1 : player.getPieces()) {
         ILinkedTile tile1 = pieces.get(piece1);
         if (tile1 == null || tile1.isHome() || tile1.isStart()) {
            continue;
         }
         tile1 = TileUtils.get(tile1, piece1.getColor(), first);

         for (IPiece piece2 : player.getPieces()) {
            if (piece2.equals(piece1)) {
               continue;
            }

            ILinkedTile tile2 = pieces.get(piece2);
            if (tile2 == null || tile2.isHome() || tile2.isStart()) {
               continue;
            }

            tile2 = TileUtils.get(tile2, piece2.getColor(), second);
            IMove m = MoveFactory.createDoubleMove(piece1, tile1, piece2, tile2);
            if (m != null) {
               moves.add(m);
            }
         }
      }

      return moves;
   }

}
